/* 
 * File:   Mundo.h
 * Author: 75.02 - Grupo 7, 2do cuatrimestre 2012.
 *
 * Created on 31 de octubre de 2012, 18:47
 */

#ifndef MUNDO_H
#define	MUNDO_H

#include "Nivel.h"
#include "ISerializable.h"
#include "Excepcion.h"

using namespace TP;
using namespace TP::Serializacion;

/* @todo: COMO SE GUARDA/ABRE UN MUNDO DESDE EL DISEÑADOR ?
 * 
 * BREVE EXPLICACION: El diseñador le pide al usuario un nombre de archivo
 * para guardar/cargar el mundo (el archivo es el XML). Si la operacion es
 * cargar, el diseñador crea un objeto Mundo y llama a mundo.cargarXML(rutaArchivo),
 * y luego tiene un mundo instanciado con lo que cargó del XML.
 * Si la operacion es guardar, primero guarda en una instancia Mundo todo
 * lo que se hizo con el diseñador, y luego llama a mundo.guardarXML(rutaArchivo).
 * 
 * QUE Y COMO GUARDA EL DISEÑADOR EN SU INSTANCIA MUNDO?:
 * Las cosas que guarda, en ppio, son:
 * 
 * Propiedades del mundo: EL NOMBRE del mundo y su CANTIDAD DE JUGADORES. Si
 * se modifica alguna de estas cosas y se da click a guardar, se llaman a los
 * metodos setNombre y setCantidadJugadores de la clase Mundo.
 * 
 * Propiedades del nivel: ID, ALTURA, ANCHURA, TIEMPO, IMAGEN FONDO. Y lo importante
 * es esto: cuando se modifica alguno de estos valores, no hay seters en Nivel
 * para cambiar los valores. Lo que se hace es borrar al nivel del vector de
 * niveles del mundo, y se llama a crearNivel (que lo instancia y lo agrega al vector)
 * La razon es xq al modificar una de estas cosas, se tiene propagar la modificacion
 * por Escenario, Perimetro, y no se si por Vector2D o lo que haya.. entonces es mas
 * facil y seguro crearlo de vuelta. 
 * 
 * Actores y Utilidades: Todas las cosas que se pusieron en el drawing area.
 * Se agregan a sus respectivos vectores en Escenario */

namespace TP {
    namespace Juego {

        class Mundo: public ISerializable {
        public:
            Mundo();
            
            Mundo (const string& pNombre);

            ~Mundo();

            /* Seters para que el diseñador pueda modificar los atributos */
            void setNombre(const string& nombre);
            
            void setCantidadJugadores(unsigned cantidad);

            const string& getNombre() const;
            
            unsigned getCantidadJugadores() const;

            /* Retorna NULL si el nivel no existia */
            /* No retorna una copia, por lo tanto no hacerle delete al puntero
             * retornado */
            Nivel* getNivel(unsigned idNivel);
            
            /* Crea un nivel. Si ya existia un nivel con ese id, se elimina y
             * se reemplaza por uno nuevo */
            void crearNivel(unsigned id, unsigned anchura, unsigned altura, unsigned tiempo, const std::string &rutaImagenFondo);

            /* Retorna false si no existia un nivel con ese id */
            bool removerNivel(unsigned id);

            /* No hacer asignaciones de mundos ni copias */
            bool operator==(const Mundo &mundo);
            
            bool operator!=(const Mundo &mundo);

            virtual string aXML();

            virtual string aXML(const string& pPath);

            virtual void parseXML (const string& pDescriptor);

            virtual TiXmlElement* aElementoXML ();

            virtual void deElementoXML (TiXmlElement* pElemento);    
            
            static Mundo* crearDeXML (const string& pDescriptor) throw (Excepcion&);
            
        private:

            /* Retorna -1 si no existia el nivel con ese id */
            int obtenerPosicionNivel(unsigned idNivel);

            string _nombre;
            unsigned _cantidadJugadores;
            std::vector<Nivel*> _niveles;

        };
    }
}

#endif	/* MUNDO_H */

